#ifndef DSPNASM_ELFFILE_H
#define DSPNASM_ELFFILE_H

#include <vector>
#include <memory>
#include <string>
#include <unordered_map>
#include <deque>
#include "nasm/elf/elf.h"
#include "nasm/type/type.h"
#include "nasm/elf/relocationItem.h"


namespace dspnasm {
    class Symbol;

/**
 * elf文件类，包含elf文件的重要内容，处理elf文件
 */

    struct ElfFile {
        std::string m_fileName;

        Elf32_Ehdr ehdr;    // 文件头
        std::vector<std::shared_ptr<Elf32_Phdr>> phdrTab; // 程序头表
        std::unordered_map<std::string, std::shared_ptr<Elf32_Shdr> > shdrTab; // 段表
        std::vector<std::string> shdrNames;   // 段名顺序
        std::unordered_map<std::string, std::deque<u8>> shdrData;  // 段数据

        std::unordered_map<std::string, std::shared_ptr<Elf32_Sym>> symTab; // //符号表
        std::vector<std::string> symNames;  // 符号名顺序
        std::vector<std::shared_ptr<RelocationItem>> relTab; // 重定位表
        std::string shstrtab;    // 段表字符串表
        std::string strtab;      // 字符串表
        std::vector<std::shared_ptr<Elf32_Rel>> relTextTab;
        std::vector<std::shared_ptr<Elf32_Rel>> relDataTab;

        // 添加一个段到段表中
        void addShdr(const std::string &sh_name, Elf32_Off sh_offset, Elf32_Word sh_size);

        void addShdr(const std::string &sh_name, Elf32_Word sh_type, Elf32_Word sh_flags, Elf32_Addr sh_addr,
                     Elf32_Off sh_offset, Elf32_Word sh_size, Elf32_Word sh_link, Elf32_Word sh_info,
                     Elf32_Word sh_addralign, Elf32_Word sh_entsize);

        // 添加符号到符号表中
        void addSymbol(std::shared_ptr<Symbol> symbol);

        // 获取段在段表中的索引
        u32 getSegIndex(const std::string &segName);

        std::shared_ptr<RelocationItem>
        addRel(const std::string &sectionName, u32 addr, const std::string &lb, u32 type);

        u32 readShdrData(const std::string &segName, char buffer[], u32 bufferSize);

        void assemblyObj();

        void writeBytes(const std::string &sectionName, const std::vector<u8> &data);

        void writeElf();

        // 填充段间的空隙
        void padSeg(const std::string &first, const std::string &second, FILE *fileOut);

        void writeElfTail(FILE *fileOut);
    };
}

#endif //DSPNASM_ELFFILE_H
